package chapter_26.reflect;

import com.sun.swing.internal.plaf.metal.resources.metal;

import java.io.*;
import java.lang.reflect.*;

/**
 * java.lang.reflect 包内
 * {@link java.lang.reflect.Constructor}
 * {@link java.lang.reflect.Field}
 * {@link java.lang.reflect.Method}
 * {@link java.lang.reflect.Array}
 * {@link java.lang.reflect.Modifier}
 * 方法的测试
 */
public class MainTest {

    public static void main(String[] args) {

        MethodTest();
        MethodTest2();

        ConstructorTest();

        FieldTest();

    }

    /**
     * {@link java.lang.reflect.Constructor} 测试方法
     */
    public static void ConstructorTest() {

        System.out.println("==========================ConstructorTest=========================");

        try {

            // Class aClass = Class.forName("java.lang.String");

            /*
             依赖注入的实现
             将实例化的类名保存到配置文件
             在运行时从配置文件中读取类名字符串,然后动态创建对象,建立依赖关系
            */
            Class aClass = Class.forName(readClassName());

            // 调用默认构造方法
            String s = (String) aClass.newInstance();
            System.out.println("默认构造方法: " + s);

            // 设置构造方法参数类型
            Class[] classes = new Class[1];
            // 第一个参数是 String 类型
            classes[0] = String.class;

            // 获取与参数对应的构造方法
            Constructor constructor = aClass.getConstructor(classes);
            // 为构造方法传递参数
            Object[] objects = new Object[1];
            // 第一个参数是 "hello"
            objects[0] = "hello";

            // 调用非默认构造方法,构造方法第一个参数是 String 类型
            String s1 = (String) constructor.newInstance(objects);
            System.out.println(s1);

        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException");
        } catch (IllegalAccessException e) {
            System.out.println("IllegalAccessException");
        } catch (InstantiationException e) {
            System.out.println("InstantiationException");
        } catch (NoSuchMethodException e) {
            System.out.println("NoSuchMethodException");
        } catch (InvocationTargetException e) {
            System.out.println("InvocationTargetException");
        }

        System.out.println("==========================ConstructorTest=========================");

    }

    /**
     * {@link java.lang.reflect.Field} 测试方法
     */
    public static void FieldTest() {

        System.out.println("==========================FieldTest=========================");

        try {
            // 动态加载 XXX 类的运行时对象
            Class aClass = Class.forName("chapter_26.reflect.Person");
            // 调用默认构造方法
            Person person = (Person) aClass.newInstance();
            System.out.println("调用默认构造方法: " + person);

            // 返回成员变量为 name 的 Field 对象
            Field name = aClass.getDeclaredField("name");
            // 设置成员变量 accessible 标志为 true
            name.setAccessible(true);
            // 为成员变量 name 赋值
            name.set(person,"Tony");

            // 返回成员变量为 age 的 Field 对象
            Field age = aClass.getDeclaredField("age");
            // 设置成员变量 accessible 标志为 true
            age.setAccessible(true);
            // 为成员变量 age 赋值
            age.set(person, 18);

            // 获取成员变量保存的数据
            System.out.printf("[name: %s, age: %d]", name.get(person), age.get(person));
            System.out.println();

        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException");
        } catch (IllegalAccessException e) {
            System.out.println("IllegalAccessException");
        } catch (InstantiationException e) {
            System.out.println("InstantiationException");
        } catch (NoSuchFieldException e) {
            System.out.println("NoSuchFieldException");
        }

        System.out.println("==========================FieldTest=========================");

    }

    /**
     * {@link java.lang.reflect.Method} 测试方法
     */
    public static void MethodTest() {

        System.out.println("==========================MethodTest=========================");

        try {
            // 动态加载 XXX 类的运行时对象
            Class aClass = Class.forName("java.lang.String");
            // 获得成员方法集合
            Method[] methods = aClass.getDeclaredMethods();
            // 遍历成员方法集合
            for (Method method : methods) {
                // 打印权限修饰符,如 public protected private
                System.out.print(Modifier.toString(method.getModifiers()));
                // 打印返回值类型名称
                System.out.print(" " + method.getReturnType().getName() + " ");
                // 打印方法名称
                System.out.print(method.getName() + "();");
                System.out.println();
            }

        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException");
        }

        System.out.println("==========================MethodTest=========================");

    }

    /**
     * {@link java.lang.reflect.Method} 测试方法
     */
    public static void MethodTest2() {

        System.out.println("==========================MethodTest2=========================");

        try {
            // 动态加载 XXX 类的运行时对象
            Class aClass = Class.forName("chapter_26.reflect.Person");
            // 调用默认构造方法
            Person person = (Person) aClass.newInstance();
            System.out.println(person);

            // 指定参数类型
            Class[] classes = new Class[2];
            // 第一个参数是 String
            classes[0] = String.class;
            // 第二个参数是 int
            classes[1] = int.class;

            // 获取 setNameAndAge 方法对象
            Method method = aClass.getMethod("setNameAndAge", classes);


            // 设置传递参数
            Object[] objects = new Object[2];
            // 第一个参数传递是 "Tony"
            objects[0] = "Tony";
            // 第二个参数传递是 18
            objects[1] = 18;
            // 调用 setNameAndAge 方法
            method.invoke(person, objects);
            System.out.println(person);


            // 获取 getName 对象
            method = aClass.getMethod("getName");
            // 调用 getName 方法
            Object o = method.invoke(person);
            System.out.println(o);

        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException");
        } catch (IllegalAccessException e) {
            System.out.println("IllegalAccessException");
        } catch (InstantiationException e) {
            System.out.println("InstantiationException");
        } catch (NoSuchMethodException e) {
            System.out.println("NoSuchMethodException");
        } catch (InvocationTargetException e) {
            System.out.println("InvocationTargetException");
        }

        System.out.println("==========================MethodTest2=========================");

    }

    /**
     * {@link java.lang.reflect.Array} 测试方法
     */
    public static void ArrayTest() {
    }

    /**
     * {@link java.lang.reflect.Modifier} 测试方法
     */
    public static void ModifierTest() {
    }

    /*
     读取配置文件
     */
    // 从 Configuration.ini 文件中读取类名
    public static String readClassName() {

        try (
                FileInputStream fileInputStream = new FileInputStream("./src/chapter_26/reflect/Configuration.ini");
                InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader)
        ) {

            // 读取文件中的第一行数据
            String s = bufferedReader.readLine();
            return s;

        } catch (FileNotFoundException e) {
            System.out.println("FileNotFoundException");
        } catch (IOException e) {
            System.out.println("IOException");
        }
        return null;
    }

}